var http = require('http');
var fs = require('fs');
var player = require('audioplayer');

var toneDir = "/resource/";
var tonenameSuffix = [".wav", ".mp3"];

var tonenameNumb = ["SYS_TONE_0", "SYS_TONE_1", "SYS_TONE_2", "SYS_TONE_3", "SYS_TONE_4", "SYS_TONE_5", "SYS_TONE_6", "SYS_TONE_7", "SYS_TONE_8", "SYS_TONE_9"];
var tonenameNumb1 = "SYS_TONE_yao";
var tonenameDot = "SYS_TONE_dian";
var tonenameUnit = ["SYS_TONE_MEASURE_WORD_ge", "SYS_TONE_MEASURE_WORD_shi", "SYS_TONE_MEASURE_WORD_bai", "SYS_TONE_MEASURE_WORD_qian"];
var tonenameHunit = ["SYS_TONE_MEASURE_WORD_wan", "SYS_TONE_MEASURE_WORD_yi", "SYS_TONE_MEASURE_WORD_sw", "SYS_TONE_MEASURE_WORD_bw", "SYS_TONE_MEASURE_WORD_qw"];

var receiptToneList = [];
var latestTaskID = [];
var taskIdCountMax = 30;
var taskIdIndex = 0;
var resDownloading = 0;
var last_broadcast_time = 0;
var last_sync_broadcast_time = 0;

function linkspeechAddAmount(amount, toneList, toneIndex, formatFlag)
{
  var numb = parseInt(amount);
  var deci = amount - numb;
  var target = numb;
  var subTarget;
  var subNumber;
  var slot;
  var factor;
  var count = 0;
  var prevSlotZero = false;
  var hundredMillionExist = false;
  var tenThousandExist = false;

  if (numb < 0 || numb >= 1000000000000) {
    console.log('amount overrange');
    return toneIndex;
  }

  deci = deci.toFixed(4);
  if (deci < 0.0001 && deci > 0.0) {
    deci = 0.0001;
  }

  for (var i = 2; i >= 0; i--) {
    factor = Math.pow(10000, i);
    if (target < factor) {
      continue;
    }

    subTarget = parseInt(target / factor);
    target %= factor;
    if (subTarget == 0) {
      continue;
    }

    if (i == 2) {
      hundredMillionExist = true;
    } else if (i == 1) {
      tenThousandExist = true;
    }

    subNumber = subTarget;
    prevSlotZero = false;

    for (var depth = 3; depth >= 0; depth--) {
      if (subNumber == 0) {
        break;
      }
      factor = Math.pow(10, depth);

      if ((hundredMillionExist == true || tenThousandExist == true) && i == 0) {
      } else if (hundredMillionExist == true && tenThousandExist == true && depth > 0 && subTarget < factor) {
      } else if (subTarget < factor) {
        continue;
      }

      slot = parseInt(subNumber / factor);
      subNumber %= factor;
      if (slot == 0 && depth == 0) {
        continue;
      }

      if ((subTarget < 20 && depth == 1) || (slot == 0 && prevSlotZero) || (slot == 0 && depth == 0)) {
      } else {
        toneList[toneIndex++] = toneDir + tonenameNumb[slot] + tonenameSuffix[formatFlag];
        count++;
        if (slot == 0 && prevSlotZero == false) {
          prevSlotZero = true;
        } else if (prevSlotZero == true && slot != 0) {
          prevSlotZero = false;
        }
      }

      if (slot > 0 && depth > 0) {
        toneList[toneIndex++] = toneDir + tonenameUnit[depth] + tonenameSuffix[formatFlag];
        count++;
      }
    }

    if (i > 0) {
      toneList[toneIndex++] = toneDir + tonenameHunit[i - 1] + tonenameSuffix[formatFlag];
      count++;
    }
  }

  if (count == 0 && numb == 0) {
    toneList[toneIndex++] = toneDir + tonenameNumb[0] + tonenameSuffix[formatFlag];
  }

  if (deci >= 0.0001) {
    toneList[toneIndex++] = toneDir + tonenameDot + tonenameSuffix[formatFlag];
    var deciString = deci.toString();
    deciString = deciString.substring(2);
    var deciArray = deciString.split('');

    for (var deciIndex = deciArray.length - 1; deciIndex >= 0; deciIndex--) {
      if (deciArray[deciIndex] != '0') {
        break;
      }
      delete deciArray[deciIndex];
    }

    deciArray.forEach(function(item) {
      if (item >= '0' && item <= '9') {
        toneList[toneIndex++] = toneDir + tonenameNumb[item - '0'] + tonenameSuffix[formatFlag];
      }
    });
  }
  return toneIndex;
}

function linkspeechPlayReceipt(receipt)
{
  var msgArray = receipt.speechs;
  var toneIndex = 0;

  var audioResFormat = 0;
  if (receipt.format == 'mp3') {
  	audioResFormat = 1;
  }

  receiptToneList.splice(0, receiptToneList.length);

  for (var msgIndex = 0; msgIndex < msgArray.length; msgIndex++) {
    var msg = msgArray[msgIndex];
    if (msg.charAt(0) == '{') {
      if (msg.length > 3 && msg.charAt(msg.length - 1) == '}') {
        if (msg.charAt(1) == '$') {
          var amount = parseFloat(msg.substring(2, msg.length - 1));
          toneIndex = linkspeechAddAmount(amount, receiptToneList, toneIndex, audioResFormat);
          //receiptToneList[toneIndex++] = toneDir + "tone_Y" + tonenameSuffix[audioResFormat];
        } else if (msg.charAt(1) == 'N' || msg.charAt(1) == 'n') {
          var msgNum = msg.substring(2, msg.length - 1);
          if (!isNaN(msgNum)) {
            var numArray = msgNum.split('');
            for (var numIndex = 0; numIndex < numArray.length; numIndex++) {
              if (numArray[numIndex] >= '0' && numArray[numIndex] <= '9') {
                receiptToneList[toneIndex++] = toneDir + "SYS_TONE_" + numArray[numIndex].toString() + tonenameSuffix[audioResFormat];
              }
            }
          }
        } else if (msg.charAt(1) == 'T' || msg.charAt(1) == 't') {
          var msgNum = msg.substring(2, msg.length - 1);
          if (!isNaN(msgNum)) {
            var numArray = msgNum.split('');
            for (var numIndex = 0; numIndex < numArray.length; numIndex++) {
              if (numArray[numIndex] >= '0' && numArray[numIndex] <= '9') {
                if (numArray[numIndex] == '1') {
                  receiptToneList[toneIndex++] = toneDir + tonenameNumb1 + tonenameSuffix[audioResFormat];
                } else {
                  receiptToneList[toneIndex++] = toneDir + "SYS_TONE_" + numArray[numIndex].toString() + tonenameSuffix[audioResFormat];
                }
              }
            }
          }
        } else {
          //var num = parseInt(msg.substring(2, msg.length - 1));
          //if (!isNaN(msg)) {
          //  var toneMapIndex = parseInt(msg);
          //  receiptToneList[toneIndex++] = toneDir + tonenameMap[toneMapIndex] + tonenameSuffix;
          //}
          console.log('unknown speech ' + msg);
        }
      } else {
        console.log('unknown speech ' + msg);
      }
    } else {
      receiptToneList[toneIndex++] = toneDir + msg + tonenameSuffix[audioResFormat];
    }
  }
  console.log('play list ' + receiptToneList);
  return player.listPlay(receiptToneList, function(){console.log('play list ' + receiptToneList + ' complete');});
}

function linkspeechPlayContent(content)
{
  var content = eval('(' + content + ')');
  player.play(content.url, function(){console.log('play ' + content.url + ' complete')});
}

function linkspeechResourceDownload(filepath, jobcode)
{
  var fileContent = fs.readSync(filepath);
  var resContent = eval('(' + fileContent + ')');

  var speechArray = resContent.audios;
  
  var audioResFormat = 0;

  if (resContent.format == 'mp3') {
  	audioResFormat = 1;
  }

  console.log('update local speech jobcode: ' + jobcode);
  for (var speechIndex = 0; speechIndex < speechArray.length; speechIndex++) {
    var speech = speechArray[speechIndex];
    console.log('update local speech id: ' + speech.id + ', url: ' + speech.url);
    var resourcePath = toneDir + speech.id + tonenameSuffix[audioResFormat];
    http.addDownload({
        url: speech.url,
        filepath: resourcePath,
        size: speech.size,
        method: 'GET',
        headers: {
          'Accept':'*/*',
        }
    });
  }
  http.startDownload({
    success: function (data) {
      console.log('amp http download result ' + data);
      resDownloading = 0;
      var eventPayload;
      if (data == 0) {
        console.log('amp http: [success] http.download');
      } else {
        console.log('amp http: [failed] http.download');
      }
      eventPayload = JSON.stringify({
        jobcode: jobcode,
        result: data
      });
      iotdev.postEvent({
        id: 'SpeechUpdateResponse',
        params: eventPayload
      });
    }
  });
}

function linkspeechResourceUpdate(resource, iotdev)
{
  var resource = eval('(' + resource + ')');
  var eventPayload;

  if (resDownloading == 1) {
  	console.log('res downloading, post result 3');
  	var resultData = 3;
    eventPayload = JSON.stringify({
      jobcode: resource.jobcode,
      result: resultData
    });
    iotdev.postEvent({
      id: 'SpeechUpdateResponse',
      params: eventPayload
    });

    return;
  }

  resDownloading = 1;
  http.addDownload({
    url: resource.url,
    filepath: "/temp.txt",
    size: 0,
    method: 'GET',
    headers: {
      'Accept':'*/*',
    }
  });
  http.startDownload({
    success: function (data) {
      console.log('http download result ' + data);
      if (data == 0) {
        console.log('http: [success] http.download');
        linkspeechResourceDownload("/temp.txt", resource.jobcode);
      } else {
        console.log('http: [failed] http.download');
        resDownloading = 0;
        iotdev.postEvent({
          id: 'SpeechUpdateResponse',
          params: {
            jobcode: resource.jobcode,
            result: data
          },
          success: function () {
            console.log('iot: [success] iot.postEvent');
          },
          fail: function () {
            console.log('iot: [failed] iot.postEvent');
          }
        });
      }
    }
  });
}

function linkspeechBroadcastTaskIDCheck(taskId)
{
  for (var idIndex = 0; idIndex < latestTaskID.length; idIndex++) {
  	if (latestTaskID[idIndex] === taskId) {
  	  return 1;
    }
  }
  return 0;
}

function linkspeechBroadcastTaskIDRecord(taskId)
{
  if (taskIdIndex >= taskIdCountMax) {
  	taskIdIndex = 0;
  }
  latestTaskID[taskIdIndex++] = taskId;
}

function linkspeechHandleService(iotdev, serviceid, request)
{
    console.log("iot service: " + serviceid);
    if (serviceid.indexOf("AudioPlayback") != -1) {
      linkspeechPlayContent(request);
    } else if (serviceid.indexOf("SpeechBroadcast") != -1 && serviceid.indexOf("SyncSpeechBroadcast") == -1) {
  	  var receipt = eval('(' + request + ')');
  	  if (linkspeechBroadcastTaskIDCheck(receipt.id) == 0) {
  	  	if (parseInt(receipt.timestamp) >= last_broadcast_time) {
          var ret = linkspeechPlayReceipt(receipt);
          if (ret == 0) {
    	    linkspeechBroadcastTaskIDRecord(receipt.id);
          }
          last_broadcast_time = parseInt(receipt.timestamp);
        } else {
          console.log('service time is behind');
        }
      }
    } else if (serviceid.indexOf("SpeechPost") != -1) {
  	  linkspeechResourceUpdate(request, iotdev);
    }
}

function linkspeechHandleSyncService(iotdev, serviceid, request)
{
    console.log("iot syncservice: " + serviceid);
    if (serviceid.indexOf("SyncSpeechBroadcast") != -1) {
      var receipt = eval('(' + request + ')');
      if (linkspeechBroadcastTaskIDCheck(receipt.id) == 0) {
      	if (parseInt(receipt.timestamp) >= last_sync_broadcast_time) {
          var ret = linkspeechPlayReceipt(receipt);
          var error_info = "no error";
          if (ret == 0) {
    	    linkspeechBroadcastTaskIDRecord(receipt.id);
          } else if (ret == -1) {
    	    error_info = "audio file not exist";
          }
          last_sync_broadcast_time = parseInt(receipt.timestamp);
          iotdev.replyService({
            payload: {
              task_id: receipt.id, result: ret == 0 ? 0 : 2, error_message: error_info
            },
            success: function() {
              console.log('iot: [success] iot.replyService');
            },
            fail: function() {
              console.log('iot: [failed] iot.replyService');
            }
          });
        } else {
          iotdev.replyService({
            payload: {
              task_id: receipt.id, result: 3, error_message: "timestamp behind last one"
            },
            success: function() {
              console.log('iot: [success] iot.replyService');
            },
            fail: function() {
              console.log('iot: [failed] iot.replyService');
            }
          });
        }
      } else {
        iotdev.replyService({
          payload: {
            task_id: receipt.id, result: 1, error_message: "task id repeat"
          },
          success: function() {
            console.log('iot: [success] iot.replyService');
          },
          fail: function() {
            console.log('iot: [failed] iot.replyService');
          }
        });
      }
    }
}

function linkspeechHandle(syncservice, iotdev, serviceid, request)
{
  if (syncservice == 1) {
    linkspeechHandleSyncService(iotdev, serviceid, request);
  } else {
  	linkspeechHandleService(iotdev, serviceid, request);
  }
}

module.exports =
{
    process: linkspeechHandle,
}